#include "GameManager.h"

#include "Enemy.h"
#include "Xp.h"
#include "Win311.h"
#include "Win2000.h"
#include "Win98.h"
#include "Win95.h"
#include "Vista.h"
#include "WinME.h"
#include "Apple.h"
#include "Hole.h"
#include "MainCharacter.h"
#include "Weapon.h"
#include "Fish.h"
#include "CustomObject.h"
#include "Bonus.h"
#include "ShootEmUp.h"


using namespace Ogre;
using namespace std;

template<> GameManager* Ogre::Singleton<GameManager>::ms_Singleton = new GameManager();

GameManager::GameManager()
{}

GameManager::~GameManager()
{}

Enemy* GameManager::createEnemy(Enemy::TypeEnemy type)
{
	Enemy* enemy = 0;
	if ( unusedEnemies.count(type) == 0 ){
		switch(type){
			case Enemy::VISTA :
				enemy = new Vista();
				break;
			case Enemy::XP :
				enemy = new Xp();
				break;
			case Enemy::APPLE :
				enemy = new Apple();
				break;
			case Enemy::WIN2000 :
				enemy = new Win2000();
				break;
			case Enemy::WINME :
				enemy = new WinME();
				break;
			case Enemy::WIN98 :
				enemy = new Win98();
				break;
			case Enemy::WIN95 :
				//TODO:
				//enemy = new Win95();
				enemy = new Win98();
				break;
			case Enemy::WIN311 :
				enemy = new Win311();
				break;
			case Enemy::HOLE:
				enemy = new Hole();
				break;
		}
		
	}
	else
	{
		enemy = unusedEnemies.lower_bound(type)->second;
		unusedEnemies.erase( unusedEnemies.lower_bound(type) );
        enemy->reset();
	}
	Ogre::Root::getSingleton().addFrameListener( enemy );
	enemies[enemy->getName().c_str()] = enemy;
	return enemy;
}

MainCharacter* GameManager::createMainCharacter(void)
{
	MainCharacter* maincharacter = new MainCharacter();
	Ogre::Root::getSingleton().addFrameListener( maincharacter );
	return maincharacter;
}

Weapon* GameManager::createWeapon(enum Weapon::WeaponType _type, enum Weapon::WeaponLevel _level)
{
	Weapon* weapon = new Weapon(_type, _level);
	if ( _type != Weapon::BUG )
		Ogre::Root::getSingleton().addFrameListener( weapon );
	return weapon;
}

Fish* GameManager::createFish(void)
{
	Fish* fish = 0;
	if ( unusedFishes.empty() )
	{
		fish = new Fish();
	}
	else
	{
		fish = unusedFishes.back();
		unusedFishes.pop_back();
		fish->reset();
	}
	Ogre::Root::getSingleton().addFrameListener( fish );
	return fish;
}

CustomObject* GameManager::createCustomObject(void)
{
	CustomObject* object = 0;
	if ( unusedCustomObjects.empty() )
	{
		string objectMesh("sapin.mesh");
		string objectName = CustomObject::DEFAULT_NAME + StringConverter::toString(CustomObject::ID);
		Entity* entity = ShootEmUp::getSingleton().getSceneManager()->createEntity(objectName, objectMesh);
		object = new CustomObject(entity);
	}
	else
	{
		object = unusedCustomObjects.back();
		unusedCustomObjects.pop_back();
		object->reset();
	}
	Ogre::Root::getSingleton().addFrameListener( object );
	return object;
}

Bonus* GameManager::createBonus(Bonus::BonusType _type)
{
	Bonus* bonus = 0;
	//if ( unusedBonus.empty() )
	//{
		bonus = new Bonus(_type);
	//}
	//else
	//{
	//	bonus = unusedBonus.back();
	//	unusedBonus.pop_back();
	//	bonus->reset();
	//}
	Ogre::Root::getSingleton().addFrameListener( bonus );
	return bonus;
}

void GameManager::destroyEnemy(Enemy* enemy)
{
	
	enemies.erase(enemy->getName().c_str());
	Ogre::Root::getSingleton().removeFrameListener( enemy );
	//unusedEnemies.push_back( enemy );
	unusedEnemies.insert( pair<Enemy::TypeEnemy, Enemy*>(enemy->getTypeEnemy(), enemy));
	enemy->getSceneNode()->detachObject( enemy->getEntity() );

	// on arret le jeu lorsque Vista est mort
	if(enemy->getTypeEnemy() == Enemy::VISTA){
		ShootEmUp::getSingleton().menuFinGagner();
	}
}

void GameManager::destroyMainCharacter(MainCharacter* maincharacter)
{
	Ogre::Root::getSingleton().removeFrameListener( maincharacter );
}

void GameManager::destroyWeapon(Weapon* weapon)
{
	Ogre::Root::getSingleton().removeFrameListener( weapon );
	weapon->getSceneNode()->detachObject( weapon->getEntity() );
}

void GameManager::destroyFish(Fish * fish)
{
	Ogre::Root::getSingleton().removeFrameListener( fish );
	unusedFishes.push_back( fish );
	fish->getSceneNode()->detachObject( fish->getEntity() );
}

void GameManager::destroyCustomObject(CustomObject * object)
{
	Ogre::Root::getSingleton().removeFrameListener( object );
	unusedCustomObjects.push_back( object );
	object->getSceneNode()->detachObject( object->getEntity() );
}

void GameManager::destroyBonus(Bonus * bonus)
{
	Ogre::Root::getSingleton().removeFrameListener( bonus );
	unusedBonus.push_back( bonus );
	bonus->getSceneNode()->detachObject( bonus->getEntity() );
}